//
//  AppDelegate.m
//  ZTIceHockey
//
//  Created by 观潮汇 on 6/7/22.
//  Copyright © 2016年 观潮汇. All rights reserved.
//

#ifndef __OPTIMIZE__
#define NSLog(...) printf("%f %s\n",[[NSDate date]timeIntervalSince1970],[[NSString stringWithFormat:__VA_ARGS__]UTF8String]);
#endif

#import "HttpRequestTool.h"
#import "QiniuSDK.h"

NSString * const spm_dataIdentifier = @"gch.datacache.tg";

@implementation UploadParam

@end

@implementation ConfigParam

- (instancetype)initWithPlaceholder:(NSString *)placeholder atCacheEnabled:(BOOL)cacheEnabled
{
    self = [super init];
    if (self) {
        self.placeholder = placeholder;
        self.cacheEnabled = cacheEnabled;
    }
    return self;
}
@end

@implementation HttpRequestTool

static id _instance = nil;

+ (instancetype)sharedInstance {
    return [[self alloc] init];
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

- (instancetype)init {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super init];
        __weak typeof(self) weakSelf = self;
        _networkStatus = [Utility networkDetection];
        
        AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
        [manager startMonitoring];
        [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            weakSelf.networkStatus = status;
            switch (status) {
                case AFNetworkReachabilityStatusUnknown:
                {
                    // 未知网络
                    NSLog(@"未知网络");
                }
                    break;
                case AFNetworkReachabilityStatusNotReachable:
                {
                    // 无法联网
                    NSLog(@"无法联网");
                    [[NotNetworkToolView shareNotNetworkToolView] show];
                }
                    break;
                case AFNetworkReachabilityStatusReachableViaWWAN:
                {
                    // 手机自带网络
                    NSLog(@"当前使用的是2G/3G/4G网络");
                    [[NotNetworkToolView shareNotNetworkToolView] hide];
                }
                    break;
                case AFNetworkReachabilityStatusReachableViaWiFi:
                {
                    // WIFI
                    NSLog(@"当前在WIFI网络下");
                    [[NotNetworkToolView shareNotNetworkToolView] hide];
                }
                    break;
            }
        }];
    });
    return _instance;
}

- (MBProgressHUD *)HUD
{
    if (!_HUD) {
        _HUD = [[MBProgressHUD alloc] initWithView:[Utility mainWindow]];
        [[Utility mainWindow] addSubview:_HUD];
    }
    return _HUD;
}

- (DataCache *)cache
{
    if (!_cache) {
        _cache = [[DataCache alloc] init];
    }
    return _cache;
}

// 组合URL后面带的参数
- (NSString *)combinationParams:(NSDictionary *)params
{
    if ([[params allKeys] count] == 0) {
        return @"";
    }
    NSMutableString *result = [[NSMutableString alloc] init];
    [result appendString:@"&"];
    for (NSString *key in [params allKeys]) {
        [result appendFormat:@"%@=%@&", key, [params objectForKey:key]];
    }
    return [result substringToIndex:result.length-1];
}

- (void)showNetworkPlaceholder:(NSString *)placeholder
{
    [self.HUD.label setText:placeholder];
    [self.HUD showAnimated:YES];
}

#pragma mark -- GET请求 --
- (void)getWithURLString:(NSString *)URLString
              parameters:(id)parameters
             configParam:(ConfigParam *)configParam
                 success:(void (^)(id responseObject))success
                 failure:(void (^)(NSError *error))failure
{
    /**
     *  ！！！不加密请用此字典，且还适用于缓存的KEY
     */
    NSMutableDictionary *para = [NSMutableDictionary dictionaryWithDictionary:parameters];
//    if (LOGINFLAG && [LOGINFLAG isEqualToString:@"YES"] && ![para objectForKey:@"id"]) {
//        [para setObject:User_ID forKey:@"id"];
//    }
    if (_networkStatus == AFNetworkReachabilityStatusUnknown || _networkStatus == AFNetworkReachabilityStatusNotReachable) {
        if (configParam && configParam.cacheEnabled) {
    
            NSDictionary *cacheSource = [self.cache getDataForURL:[URLString stringByAppendingString:[self combinationParams:para]]];
            if (cacheSource) {
                
                NSLog(@"网络断开，获取缓存数据成功");
                if (success) {
                    success(cacheSource);
                }
            }
            else
            {
                NSLog(@"网络断开，获取缓存数据失败");
                if (failure) {
                    failure(nil);
                }
                [Utility showHint:@"请连接网络"];
            }
        }
        else
        {
            NSLog(@"网络断开，不支持网络缓存数据");
            if (failure) {
                failure(nil);
            }
            [Utility showHint:@"请连接网络"];
        }
    }
    else
    {
        if (configParam && configParam.placeholder)
        {
            [self showNetworkPlaceholder:configParam.placeholder];
        }
        
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        /**
         *  可以接受的类型
         */
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        /**
         *  请求队列的最大并发数
         */
        manager.operationQueue.maxConcurrentOperationCount = 5;
        /**
         *  请求超时的时间
         */
        manager.requestSerializer.timeoutInterval = 30;
        
//        /**
//         *  ！！！加密请用此字典
//         */
//        NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
//        if (configParam.isEncrypt) {
//        }
//        configParam.isEncrypt?dictionary:para
        __weak typeof(self) weakself = self;
        [manager GET:URLString parameters:para progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            if (configParam && configParam.placeholder) {
                [weakself.HUD hideAnimated:YES];
            }
        
            if (success) {
                id source = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
                NSLog(@"currentURL=%@", task.currentRequest.URL);
                NSLog(@"responseObject=%@", source);

                NSInteger status = [source objectForKey:@"code"]?[[source objectForKey:@"code"] integerValue]:-9527;
                if (status == 1 || ![URLString hasPrefix:kBase_url(@"")]) {
                    NSLog(@"请求数据成功");
                    if (configParam && configParam.cacheEnabled) {
                        NSLog(@"缓存网络数据");
                        /* 缓存网络数据 */
                        [weakself.cache setData:source forURL:[URLString stringByAppendingString:[weakself combinationParams:para]]];
                    }
                    if (success) {
                        success(source);
                    }
                }
                else
                {
                    NSLog(@"数据返回失败");
                    if (success) {
                        success(source);
                    }
                    
                }
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            if (configParam && configParam.placeholder) {
                [weakself.HUD hideAnimated:YES];
            }
            [ErrorCode errorCodeAnalytical:error];
            if (failure) {
                failure(error);
            }
        }];
    }
}

#pragma mark -- GET请求 --
- (void)getWithURLString:(NSString *)URLString
              parameters:(id)parameters
                 success:(void (^)(id))success
                 failure:(void (^)(NSError *))failure {
    ConfigParam *configParam = [[ConfigParam alloc] initWithPlaceholder:nil atCacheEnabled:YES];
    if ([URLString isEqualToString:kBase_url(@"/userController/userLogin")]||[URLString isEqualToString:kBase_url(@"/userController/registerUser")]||[URLString isEqualToString:kBase_url(@"/userController/forgetPassword")]||[URLString isEqualToString:kBase_url(@"/userController/identifyingCode")]) {
        configParam.cacheEnabled=NO;
    }else{
        configParam.cacheEnabled=YES;
    }
    
    [configParam setIsEncrypt:NO];
    [self getWithURLString:URLString parameters:parameters configParam:configParam success:success failure:failure];
}

#pragma mark -- POST请求 --
- (void)postWithURLString:(NSString *)URLString
               parameters:(id)parameters
                  success:(void (^)(id))success
                  failure:(void (^)(NSError *))failure {
    
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
    NSMutableDictionary *para = [NSMutableDictionary dictionaryWithDictionary:parameters];
    if (LOGINFLAG && [LOGINFLAG isEqualToString:@"YES"] && ![para objectForKey:@"id"]) {
        [para setObject:User_ID forKey:@"id"];
    }
//    [self showNetworkPlaceholder:@"请稍等..."];
    __weak typeof(self) weakself = self;
    NSLog(@"%@", para);
    [manager POST:URLString parameters:para progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        [weakself.HUD hideAnimated:YES];
        if (success) {
            id source = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
           
            if (success) {
                success(source);
            }
           
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [ProgressHUD dismiss];
        [ErrorCode errorCodeAnalytical:error];
        if (failure) {
            failure(error);
        }
    }];
}

#pragma mark -- POST/GET网络请求 --
- (void)requestWithURLString:(NSString *)URLString
                  parameters:(id)parameters
                        type:(HttpRequestType)type
                     success:(void (^)(id))success
                     failure:(void (^)(NSError *))failure {
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    switch (type) {
        case HttpRequestTypeGet:
        {
            [manager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                if (success) {
                    success(responseObject);
                }
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                if (failure) {
                    failure(error);
                }
            }];
        }
            break;
        case HttpRequestTypePost:
        {
            [manager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                if (success) {
                    success(responseObject);
                }
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                if (failure) {
                    failure(error);
                }
            }];
        }
            break;
    }
}

#pragma mark -- 上传图片 --
- (void)uploadWithURLString:(NSString *)URLString
                 parameters:(id)parameters
                uploadParam:(UploadParam *)uploadParam
                    success:(void (^)(id responseObject))success
                    failure:(void (^)(NSError *error))failure {
    
    __weak typeof(self) weakself = self;
    [self showNetworkPlaceholder:@"请稍等..."];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
   
    NSMutableDictionary *para = [NSMutableDictionary dictionaryWithDictionary:parameters];
    if (LOGINFLAG && [LOGINFLAG isEqual:@YES]) {
    }
    [manager POST:URLString parameters:para constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:uploadParam.data name:uploadParam.name fileName:uploadParam.filename mimeType:uploadParam.mimeType];
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
       
        [weakself.HUD hideAnimated:YES];
        if (success) {
            id source = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
            NSLog(@"currentURL=%@", task.currentRequest.URL);
            NSLog(@"responseObject=%@", source);
            
            NSInteger status = [source objectForKey:@"code"]?[[source objectForKey:@"code"] integerValue]:-9527;
            if (status == 0) {
                NSLog(@"上传数据成功");
                if (success) {
                    success(source);
                }
            }
            else
            {
                NSLog(@"上传返回失败");
                if (failure) {
                    failure(nil);
                }
                [ErrorCode errorStatusAnalytical:source];
            }
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       
        [weakself.HUD hideAnimated:YES];
        [ErrorCode errorCodeAnalytical:error];
        if (failure) {
            failure(error);
        }
    }];
}

- (void)uploadWithFileName:(NSString *)fileName
             uploadFileArr:(NSArray *)fileArr
                     token:(NSString *)token
                   success:(void (^)(id responseObject))success
                   failure:(void (^)(NSError *error))failure
{
    __weak typeof(self) weakself = self;
    [self showNetworkPlaceholder:@"请稍等..."];
    
    int index = 0;
    __block NSMutableArray *aKeys = [NSMutableArray array];
    
    for (id file in fileArr) {
        
        index ++;
        
        NSString *aKey = [NSString stringWithFormat:@"%@/%@_%d_%@.png", QiniuBucket, fileName, index, [Utility currentTime:[NSDate date]]];
        NSData *data;
        if ([file isKindOfClass:[UIImage class]]) {
            data = UIImageJPEGRepresentation(file, .5);
        }
        QNUploadManager *upManager = [[QNUploadManager alloc] init];
        [upManager putData:data key:aKey token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
            NSLog(@"%@\n%@\n%@", info, key, resp);
            if (info.statusCode == 200) {
                [aKeys addObject:[NSString stringWithFormat:@"%@%@", QiniuHostDomain, key]];
                
                if (aKeys.count == fileArr.count) {
                    [weakself.HUD hideAnimated:YES];
                    if (success) {
                        success(aKeys);
                    }
                }
            }
            else
            {
                [Utility showHint:@"上传失败"];
                [weakself.HUD hideAnimated:YES];
                if (failure) {
                    failure(nil);
                }
            }
        } option:nil];
    }
}

#pragma mark - 下载数据
- (void)downLoadWithURLString:(NSString *)URLString parameters:(id)parameters progerss:(void (^)())progress success:(void (^)())success failure:(void (^)(NSError *))failure {
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URLString]];
    NSURLSessionDownloadTask *downLoadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        if (progress) {
            progress();
        }
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        return targetPath;
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        if (failure) {
            failure(error);
        }
    }];
    [downLoadTask resume];
}


#pragma mark - NSDictionary->Model
+ (NSMutableArray *)ModelTransformationWithResponseObject:(id)responseObject modelClass:(Class)modelClass
{
    NSMutableArray *array = [NSMutableArray array];
    
    NSArray *appcications = responseObject[@"applications"];
    for (NSDictionary *dict in appcications)
    {
        [array addObject:[modelClass mj_objectWithKeyValues:dict]];
    }
    
    return array;
}

@end

@implementation DataCache

- (instancetype)init {
    self = [super init];
    if(self) {
        NSArray  *paths         = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString *rootCachePath = [paths firstObject];
        
        _fileManager    = [NSFileManager defaultManager];
        _cachePath      = [rootCachePath stringByAppendingPathComponent:spm_dataIdentifier];
        
        if(![_fileManager fileExistsAtPath:spm_dataIdentifier]) {
            [_fileManager createDirectoryAtPath:_cachePath withIntermediateDirectories:NO attributes:nil error:nil];
        }
    }
    return self;
}

- (void)setData:(NSDictionary *)dic forURL:(NSString *)URL
{
    NSString *fileExtension = [[URL componentsSeparatedByString:@"/"] lastObject];
    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:dic forKey:@"Some Key Value"];
    [archiver finishEncoding];
    [data writeToFile:[_cachePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%lu.%@", (unsigned long)URL.hash, fileExtension]] atomically:YES];
}

- (NSDictionary *)getDataForURL:(NSString *)URL
{
    NSString *fileExtension = [[URL componentsSeparatedByString:@"/"] lastObject];
    NSString *path = [_cachePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%lu.%@", (unsigned long)URL.hash, fileExtension]];
    if([_fileManager fileExistsAtPath:path]) {
        
        NSData *data = [NSData dataWithContentsOfFile:path];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        NSDictionary *myDictionary = [unarchiver decodeObjectForKey:@"Some Key Value"];
        [unarchiver finishDecoding];
        return myDictionary;
    }
    return nil;
}

- (void)removeCache
{
    if ([_fileManager fileExistsAtPath:_cachePath]) {
        [_fileManager removeItemAtPath:_cachePath error:nil];
    }
}

@end
